<!-- HTML header for doxygen 1.8.13-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.9.2"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Key Value Storage (kv-store)</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen_style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><a href="http://www.cypress.com/"><img alt="Logo" src="logo.png"/></a></td>
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">Key Value Storage (kv-store)</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.2 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(document).ready(function(){initNavTree('index.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div><div class="header">
  <div class="headertitle"><div class="title">Key Value Storage Library </div></div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p ><a class="anchor" id="md_source_support_kv_store_README_doxygen"></a> </p>
<h1><a class="anchor" id="autotoc_md1"></a>
Overview</h1>
<p >This library provides a convenient way to store information as key-value pairs in non-volatile storage.</p>
<h1><a class="anchor" id="autotoc_md2"></a>
Features</h1>
<ul>
<li>Supports any storage which can be modeled as a block device, including internal flash or external flash (e.g. via QSPI).</li>
<li>Allows partitioning storage by instantiating multiple instances of the library.</li>
<li>Designed to be resilient to power failures.</li>
<li>Designed to promote even wear of the storage.</li>
</ul>
<h1><a class="anchor" id="autotoc_md3"></a>
Storage</h1>
<p >The utility operates on the assumption that the underlying storage is a block device which may not have the same program and erase sizes. The application is required to provide an implementation for a block device interface (<code><a class="el" href="group__group__kvstore.html#structmtb__kvstore__bd__t" title="Block device interface.">mtb_kvstore_bd_t</a></code>) that describes the characteristics of the underlying storage and defines basic operations (read, write, erase). See <code>mtb_kvstore_init</code> for a description of the constraints that the storage must satisfy. Code snippets using the serial-flash library (External Flash) and HAL flash driver (Internal Flash) are provided as example implementations of the storage interface in the Getting Started section in the API Reference Guide.</p>
<h1><a class="anchor" id="autotoc_md4"></a>
Keys and Values</h1>
<h2><a class="anchor" id="autotoc_md5"></a>
Keys</h2>
<p >Keys are ASCII strings (Null terminated). The maximum key length is defined by <code>MTB_KVSTORE_MAX_KEY_SIZE</code>. This can be overridden by the application by adding <code>DEFINES+=MTB_KVSTORE_MAX_KEY_SIZE=&lt;value&gt;</code> with the desired value to application Makefile.</p>
<h2><a class="anchor" id="autotoc_md6"></a>
Values</h2>
<p >Values are arbitrary length binary data. By default it is assumed that each value (plus the header info of ~20 bytes) is less than the <code><a class="el" href="group__group__kvstore.html#structmtb__kvstore__bd__t" title="Block device interface.">mtb_kvstore_bd_t</a></code> <code>erase_size</code>. If this is not true, a define <code>MTB_KVSTORE_MAX_VALUE_SIZE</code> must be defined with the actual max value size. NOTE: This define is not currently used, but will be in a future update. Setting it now will help ensure the application works properly with newer versions of the kv-store library.</p>
<h1><a class="anchor" id="autotoc_md7"></a>
RTOS Integration</h1>
<p >In an RTOS environment, the library can be made thread safe by adding the <code>RTOS_AWARE</code> component (COMPONENTS+=RTOS_AWARE) or by defining the <code>CY_RTOS_AWARE</code> macro (DEFINES+=CY_RTOS_AWARE). This causes all API to be protected by a mutex to serialize access to underlying storage device. The kvstore library must be initialized after the RTOS kernel has started for the mutex to be initialized safely. The default timeout for the mutex is defined by <code>MTB_KVSTORE_MUTEX_TIMEOUT_MS</code> and can be overridden by specifying <code>DEFINES+=MTB_KVSTORE_MUTEX_TIMEOUT_MS=&lt;value&gt;</code> with the application Makefile.</p>
<p >When determining a suitable timeout, consider that the execution time for KVStore modifying operations is impacted by several factors:</p><ul>
<li>The size of the key and value being written</li>
<li>If garbage collection is required (see "Garbage collection" section for details) to complete a modification, this operation must erase half of the storage which was provided for kv-store to use. This is a potentially lengthy operation. The <code>mtb_kvstore_ensure_capacity</code> function can be used to trigger garbage collection, if necessary, in less timing sensitive contexts.</li>
<li>All operations are impacted by the write performance of the underlying storage device. For more details, see the datasheet of the selected MCU (for internal flash) or the external memory device.</li>
</ul>
<h1><a class="anchor" id="autotoc_md8"></a>
Design details</h1>
<h2><a class="anchor" id="autotoc_md9"></a>
Sequential log of records</h2>
<p >The key-value pairs are stored sequentially as records. Each operation appends a new record to the next available program block. If multiple records exist for the same key, the record at the highest address takes precedence over those that came before it. In an update operation, a new record with the key and updated value is appended, overriding the previous value. In a delete operation, a new record with the key and a "deleted" flag is appended.</p>
<h2><a class="anchor" id="autotoc_md10"></a>
Memory Layout</h2>
<p >The address space provided by the application is divided into two areas. At any given time, one area is designated as active and the other as swap. All key/value pair records are stored in the active area. Each time garbage collection is performed, the active and swap area designations are reversed. The first record in the active area is an area header used to identify the current active area during initialization. This means that one half of the provided storage space is available for key value storage. </p><div class="fragment"><div class="line">          active area                       swap area</div>
<div class="line">+-----------------------------+  +-----------------------------+</div>
<div class="line">|      area header record     |  |                             |</div>
<div class="line">+-----------------------------+  |                             |</div>
<div class="line">|      key value record 1     |  |                             |</div>
<div class="line">+-----------------------------+  |                             |</div>
<div class="line">|      key value record 2     |  |                             |</div>
<div class="line">|                             |  |                             |</div>
<div class="line">+-----------------------------+  |                             |</div>
<div class="line">|      key value record 3     |  |                             |</div>
<div class="line">+-----------------------------+  |                             |</div>
<div class="line">|        free space           |  |                             |</div>
<div class="line">|                             |  |                             |</div>
<div class="line">+-----------------------------+  +-----------------------------+</div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md11"></a>
Record</h2>
<p >Each record contains a record header (<code>_mtb_kvstore_record_header_t</code>) that contains metadata including key/value sizes and a CRC. This is followed by the key and value data. The record is padded to the program size.</p>
<div class="fragment"><div class="line">+---------------------+-------------------------+--------------------------------+---------------+</div>
<div class="line">| Record Header       | Key                     | Data                           | prog size pad |</div>
<div class="line">+---------------------+-------------------------+--------------------------------+---------------+</div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md12"></a>
RAM table</h2>
<p >A table that contains a hash for every key and the corresponding offset of the latest record for that key in storage is maintained in RAM. This table is built from storage during initialization and is updated on every subsequent operation. The key is verified by matching the key in the record in the storage. If it does not match the next entry with the same hash in the RAM table is checked. This allows for the possibility that multiple distinct keys may hash to the same value.</p>
<h2><a class="anchor" id="autotoc_md13"></a>
Garbage collection</h2>
<p >The garbage collection operation copies all of the non-obsolete records (i.e. all of those listed in the RAM table) into the swap area. The swap area is then marked as the new active area by programming the area header at the start. The former active area is erased and becomes the new swap area. Garbage collection is performed in the following scenarios:</p><ul>
<li>The active area does not have sufficient space remaining to perform a requested modification (add, update, delete) and the active area contains obsolete records.</li>
<li>A corrupted record is encountered during initialization. This may happen if a power failure occurs while the a record is being appended during a modifying operation. The garbage collection operation will copy all non-obsolete records preceding the corrupted record.</li>
<li>The <code>mtb_kvstore_ensure_capacity</code> function is called and the active area does not contain the requested amount of space available for immediate usage.</li>
</ul>
<p ><b>NOTE:</b> Due to the garbage collection operation, write and delete operations may consume significantly more time than typical when the active area becomes full. Hence, they must not be called from timing critical code.</p>
<h1><a class="anchor" id="autotoc_md14"></a>
Dependencies</h1>
<ul>
<li><a href="https://github.com/infineon/abstraction-rtos">abstraction-rtos</a> library if the <code>CY_RTOS_AWARE</code> macro is defined in the Makefile</li>
</ul>
<h1><a class="anchor" id="autotoc_md15"></a>
More information</h1>
<ul>
<li><a href="https://infineon.github.io/kv-store/html/modules.html">API Reference Guide</a></li>
<li><a href="http://www.cypress.com">Cypress Semiconductor, an Infineon Technologies Company</a></li>
<li><a href="https://github.com/infineon">Infineon GitHub</a></li>
<li><a href="https://www.cypress.com/products/modustoolbox-software-environment">ModusToolbox™</a></li>
</ul>
<hr  />
<p> © Cypress Semiconductor Corporation (an Infineon company) or an affiliate of Cypress Semiconductor Corporation, 2021. </p>
</div></div><!-- PageDoc -->
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part
<div id="nav-path" class="navpath">
    <ul>
        <li class="footer">
            Generated for <b>Key Value Storage (kv-store)</b> by <b>Cypress Semiconductor Corporation</b>.
            All rights reserved.
        </li>
    </ul>
</div>
-->
</body>
</html>
